package com.yangrong.thread.chapter9;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Optional;

public class BooleanLock implements Lock {

	// true锁已经被占用
	// false锁空闲
	private boolean initValue;

	private Collection<Thread> blockedThreadCollection = new ArrayList<>();

	// 记住获取锁的线程，防止其他线程释放锁
	private Thread currentThread;

	public BooleanLock() {
		this.initValue = false;
	}

	@Override
	public synchronized void lock() throws InterruptedException {
		// TODO Auto-generated method stub
		while (initValue) {
			blockedThreadCollection.add(Thread.currentThread());
			this.wait();
		}
		blockedThreadCollection.remove(Thread.currentThread());
		this.initValue = true;
		this.currentThread = Thread.currentThread();
	}

	@Override
	public synchronized void lock(long mills) throws InterruptedException, TimeOutException {
		// TODO Auto-generated method stub
		if (mills <= 0)
			lock();
		long hasRemaining = mills;
		long endTime = System.currentTimeMillis() + mills;
		while (initValue) {
			if (hasRemaining <= 0)
				throw new TimeOutException("Time out");
			blockedThreadCollection.add(Thread.currentThread());
			this.wait(mills);
			hasRemaining = endTime - System.currentTimeMillis();
		}

		this.initValue = true;
		this.currentThread = Thread.currentThread();
	}

	@Override
	public synchronized void unlock() {
		// TODO Auto-generated method stub
		if (Thread.currentThread() == currentThread) {
			this.initValue = false;
			Optional.of(Thread.currentThread().getName() + " release the lock monitor.").ifPresent(System.out::println);
			this.notifyAll();
		}
	}

	@Override
	public Collection<Thread> getBlockedThread() {
		// TODO Auto-generated method stub
		return Collections.unmodifiableCollection(blockedThreadCollection);
	}

	@Override
	public int getBlockedSize() {
		// TODO Auto-generated method stub
		return 0;
	}

}
